/**
 * 
 */
package com.comp6231.replica1;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.omg.CORBA.ORB;

import com.comp6231.DPIS.StationServer;
import com.comp6231.DPIS.StationServerHelper;
import com.comp6231.common.Request;
import com.comp6231.coordinator.Coordinator;
import com.comp6231.replica1.data.Stations;
import com.comp6231.replica1.server.StationServerSystem;

/**
 * @author Farzana Alam
 * 
 */
public class CoordinatorReplica1 extends Coordinator {

	/**
	 * Declare the server
	 */
	StationServer server = null;
	// my own reference table to avoid unnecessary I/O
	Map<String, String> stationIOR = new HashMap<String, String>();
	/**
	 * Class attributes to hold the badge number of the office using the system
	 * currently and the server reference
	 */
	static String stationName = null;

	public CoordinatorReplica1(String hostName, String dataUDPPort,
			String controlUDPPort, String replicaName, int replicaID,
			Hashtable<String, String[]> coordinatorReplicaList,
			Hashtable<String, String[]> frontEndList) {
		super(hostName, dataUDPPort, controlUDPPort, replicaName, replicaID,
				coordinatorReplicaList, frontEndList);
		new Thread(new StationServerSystem()).start();
	}

	@Override
	public String invokeMethod(Request request) {

		RequestParser reqParser = new RequestParser(request.getOperation(),
				request.getOperationArguments());

		return callLocalServerMethod(request, reqParser, request.getOperation());
	}

	private String callLocalServerMethod(Request request,
			RequestParser reqParser, String operation) {

		this.loadServer(reqParser.getBadgeID());

		StringBuilder result = new StringBuilder();
		String locallyProcessedResult = "Success";
		String replyFromServer = null;

		switch (operation.trim().toUpperCase()) {
		case "CREATECRECORD":
			replyFromServer = String.valueOf(server.createCRecord(
					reqParser.getBadgeID(), reqParser.getFirstName(),
					reqParser.getLastName(), reqParser.getDescription(),
					reqParser.getStatus()));
			replyFromServer = (replyFromServer.equalsIgnoreCase("true") ? "Success"
					: "Fail");
			break;
		case "CREATEMRECORD":
			replyFromServer = String.valueOf(server.createMRecord(
					reqParser.getBadgeID(), reqParser.getFirstName(),
					reqParser.getLastName(), reqParser.getAddress(),
					reqParser.getLastDate(), reqParser.getLastLocation(),
					reqParser.getStatus()));
			replyFromServer = (replyFromServer.equalsIgnoreCase("true") ? "Success"
					: "Fail");
			break;
		case "GETRECORDCOUNTS":
			replyFromServer = server.getRecordCounts(reqParser.getBadgeID());
			break;
		case "EDITRECORD":
			replyFromServer = String.valueOf(server.editRecord(
					reqParser.getBadgeID(), reqParser.getLastName(),
					reqParser.getRecordID(), reqParser.getStatus()));
			replyFromServer = (replyFromServer.equalsIgnoreCase("true") ? "Success"
					: "Fail");
			break;
		case "TRANSFERRECORD":
			replyFromServer = String.valueOf(server.transferRecord(
					reqParser.getBadgeID(), reqParser.getRecordID(),
					reqParser.getRemoteStationServerName()));
			replyFromServer = (replyFromServer.equalsIgnoreCase("true") ? "Success"
					: "Fail");
			break;
		default:
			locallyProcessedResult = "Fail";
			break;
		}

		if (replyFromServer == null) {
			replyFromServer = "";
			locallyProcessedResult = "Fail";
		}
		result.append(locallyProcessedResult + " ## ").append(replyFromServer);

		if (locallyProcessedResult.equalsIgnoreCase("Success")) {
			System.out
					.println(request.getRequestID() + " is processed locally");
			request.setLocallyProcessed(true);
		}

		return result.toString();
	}

	/**
	 * method to get police officer badge number and verify it to ensure its a
	 * valid and load the appropriate station server
	 * 
	 * @return
	 */
	private boolean loadServer(String badgeId) {
		// verify and save the badge id
		Pattern pattern = Pattern.compile("\\d+");
		Matcher matcher = pattern.matcher(badgeId);
		String tempStationName = "";
		matcher.find();
		tempStationName = badgeId
				.substring(0, badgeId.indexOf(matcher.group())).toUpperCase();
		stationName = Stations.getEnumValue(tempStationName)
				.getPoliceStationType();

		ORB orb = ORB.init(new String[] { "" }, null);

		// check if the ior mapping exists in hash map
		String ior = stationIOR.get(stationName);
		if (ior == null) {
			// accessing the server first time, so get it from file
			BufferedReader br;
			try {
				br = new BufferedReader(new FileReader(
						System.getProperty("user.dir")
								+ "/src/com/comp6231/replica1/server/"
								+ stationName + "Ior.txt"));
				ior = br.readLine();
				br.close();
			} catch (FileNotFoundException e) {
				System.out.println("Station Server IOR File not found");
				return false;
			} catch (IOException e) {
				System.out.println("Exception opening Station Server IOR File");
				return false;
			}
			stationIOR.put(stationName, ior);
		}

		org.omg.CORBA.Object o = orb.string_to_object(ior);
		server = StationServerHelper.narrow(o);

		return true;
	}

}
